/**
 * ----------------------------------------------使用说明--------------------------------------------
 * 
 * 并行高速算法处理接口, ---由江苏捷世智通提供
 *
 * 2023-03-10: member 
 *  hanguangxue <hanguangxue_x@163.com> - C    for PCIE driver and CPU  do CNN
 *  qianmen <qianmen@xx.com>            - FPGA for PCIE driver and FPGA do CNN
 * 
 * [中文] 该程序用于并行高速算法处理类接口, 提供需要对相应算法做加速的模块
 * 
 * [English] This program is used for parallel high speed algorithm processing class interface,
 * provides the need to do the corresponding algorithm to accelerate the module
 * 
 * version 1.0, 2023-03-10
 *    support CNN Accelerate
 * 
 * 
 * ----------------------------------------------性能说明--------------------------------------------
 * 
 * 经过测试, 以下为各平台对卷积处理的性能对比
 * arm, 飞腾D2000, 64位,  8核, 1024*1024, 9
 *   七核, 5000, 104s    ×
 *   七核, 1000, 21s     ×
 *   六核, 1000, 23s     ×
 *   五核, 1000, 28s     ×
 *   四核, 1000, 34s     ×
 * 
 * x86,因特尔处理, 64位, 32核, 1024*1024, 9
 *   七核 5000次  26s    √  
 *   七核 1000次  5s     √
 *   六核 1000次  6s     √
 *   四核 1000次  10s    ×
 * 
 */

#ifndef __JSZT_CNN__H
#define __JSZT_CNN__H

#define     uint8   unsigned char
#define     uint16  unsigned short

typedef enum {
    JS_OK,
    JS_FAILED,
    /** 参数错误 */
    JS_ERROR_BORDER,            //卷积数据和卷积核边界错误, 如果卷积数据相对卷积核来说过小则报此错
    JS_ERROR_CONFIG,            //配置出错, eg: 选择CPU模式的时候, CPU核数给的0

    /** 系统错误 */
    JS_ERROR_CREATE__TH,         //创建线程资源失败,针对某些裁剪后的linux,对线程资源有限制,如果超出系统最大数会返回错误
    JS_ERROR_RELEASE_TH,         //线程销毁时返回该错误, 销毁线程需要调用 jszt_setEnd 接口 
    JS_ERROR_MALLOC,             //堆内存申请出错
    JS_ERROR_NULL,               //空指针异常
    JS_ERROR_CNNING,             //执行卷积运算时出错
} JSZT_CODE;

typedef enum {
    CALCULAT_FPGA,
    CALCULAT_CPU,
} MODE_CALCULAT;

typedef struct {
    uint8 * stream;              //流输入, 输入为处理后的流, 1024*1024, 一位占 8bit, 也就是一字节
    uint16  width;               //流矩阵宽度, width * height 则为 stream 的实际长度
    uint16  height;              //流矩阵长度
    uint8 * cnnker;              //卷积核, 同样的一位占 8bit, 长度根据 cnnker_matrix_len 输入解析, 是数组 cnnker_matrix_len (x1+x2+..+x4)²
    uint8   ckrlen[4];           //卷积核矩阵长度, 参数 @CNNKER_XX, 按次序输入, 如果是只需要一次, 则 [x,0,0,0], 需要计算2次, 则[x1, x2, 0, 0]

    /* 返回参数 */
    uint8 * dstream;             //处理后的数据, 申请内存大小 >= (width-ckerlen+1)*(height-ckerlen+1)
    uint16  dwidth;              //处理后矩阵 宽
    uint16  dheight;             //处理后矩阵 高
    int     dcnt;                //计算次数
} CNN_PARA;

/**
 * @details     初始化相关资源
 * @param mode  初始化计算类型
 * @return  0: 返回OK, 否则返回失败, 查看对应错误信息
 */
extern JSZT_CODE jszt_init(MODE_CALCULAT mode, int CPUS);

/**
 * @details 开始计算前预备工作
 * @return  0: 返回OK, 否则返回失败, 查看对应错误信息
 */
extern JSZT_CODE jszt_setReady();

/**
 * @param cnnPara 调用时需要的参数
 * @return        处理后的数据长度, 处理后的数据放在 dstream 中, 直接从 stream 中读取指定长度数据即可
*/
extern JSZT_CODE jszt_CNN(const CNN_PARA *cnnPara);

/**
 * @details 计算完成后需要释放的资源
 * @return  0: 返回OK, 否则返回失败, 查看对应错误信息
 */
extern JSZT_CODE jszt_setEnd();

/**
 * @details 程序结束后需要调用释放的资源
 * @return  0: 返回OK, 否则返回失败, 查看对应错误信息
*/
extern JSZT_CODE jszt_destroy();

#endif  // !__JSZT_CNN__H